package membership

import (
	"context"
	"errors"
	v1 "gf-xb-api/api/membership/v1"
	"gf-xb-api/cwt/mymiddleware"
	"gf-xb-api/internal/consts"
	"gf-xb-api/internal/model/do"
	"gf-xb-api/internal/model/dto"
	"gf-xb-api/internal/service"

	"gf-xb-api/utility/xcaptcha"
	"gf-xb-api/utility/xconfig"
	"gf-xb-api/utility/xredis"
	"gf-xb-api/utility/xstr"

	"github.com/gogf/gf/v2/database/gredis"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/util/gconv"
)

func (c *ControllerV1) Login(ctx context.Context, req *v1.LoginReq) (res *v1.LoginRes, err error) {

	// 校验验证码
	conf, err := xconfig.GetCaptchaConfig()
	if err != nil {
		return nil, err
	}

	if conf.Open {
		if xstr.IsBlank(req.CaptchaId) || xstr.IsBlank(req.CaptchaCode) {
			return nil, errors.New(consts.CAPTCHA_BLANK)
		}

		if ok := xcaptcha.Verify(req.CaptchaId, req.CaptchaCode); !ok {
			return nil, errors.New(consts.CAPTCHA_INVALID)
		}
	}

	user, err := service.Membership().Login(ctx, &dto.LoginInput{
		Username:   req.Username,
		Password:   req.Password,
		DeviceType: req.DeviceType,
	})

	if err != nil {
		return nil, err
	}

	// 获得jwt token
	r := g.RequestFromCtx(ctx)
	r.SetCtxVar(consts.JWT_INFO_USER, user)

	token, _ := mymiddleware.Auth().LoginHandler(ctx)

	// r := g.RequestFromCtx(ctx)
	// uuid := r.GetCtxVar(consts.JWT_INFO_UUID).String()
	uuid := user.Uuid

	// 写入登录日志
	loginLog := do.SysLoginLog{
		UserUuid:   uuid,
		DeviceType: req.DeviceType,
		Status:     consts.USER_LOGIN,
		Ip:         r.GetClientIp(),
	}

	// 登录日志
	err = service.LoginLog().Create(ctx, loginLog)
	if err != nil {
		return nil, err
	}

	// 保存在Redis中
	timeoutSeconds := g.Config().MustGet(ctx, consts.JWT_TIMEOUT).Int()
	redisKey := xredis.JwtTokenKey(uuid, req.DeviceType)
	expiry := gconv.PtrInt64(timeoutSeconds)

	g.Redis().Set(ctx, redisKey, token, gredis.SetOption{
		TTLOption: gredis.TTLOption{
			EX: expiry,
		},
	})

	data := &v1.LoginRes{
		Type:     consts.TOKENTYPE,
		Token:    token,
		ExpireIn: g.Config().MustGet(ctx, consts.JWT_TIMEOUT).Int(), // 单位秒
	}

	return data, err
}
